import { defer, isType } from '../helpers/utils';
import { validate } from './_validate';
import { ValidatorMessage } from '../message/index';
import {
	IValidateResult,
	IValidateRule,
	IValidatorPatterns,
} from '../interfaces/validataor.interface';
import { PubSub } from '../helpers/pub-sub';

// 验证器选项参数
type IValidatorOptions = {};

// 语言类型
enum LangType {
	// 中文
	'zh' = 'zh-CN',
	// 英文
	'en' = 'en-US',
}
// 状态
enum ValidateState {
	// 空闲
	IDLE = 'idle',
	// 等待运行中
	PENDING = 'pending',
}

/**
 * 表单验证器
 */
export class Validator {
	// 版本号
	private readonly _version = '1.0.0';

	// 状态
	private state: ValidateState = ValidateState.IDLE;

	// 发布订阅
	private readonly _pubSubCenter = new PubSub();

	// 验证message类
	private readonly validatorMessage = new ValidatorMessage();

	constructor(
		private readonly rules: Record<string, IValidateRule | IValidateRule[]>,
		private readonly options?: IValidatorOptions,
	) {}

	// 验证结果缓存
	private resultCache: Record<string, IValidateResult> = {};

	// error message
	private errorMessage: any[] = [];

	// 当前验证状态
	get resultState(): boolean {
		const resultList = Object.values(this.setResultCache);
		return (
			this.state === ValidateState.IDLE &&
			resultList.length > 0 &&
			resultList.some((result) => result.result === false)
		);
	}

	/**
	 * 设置语言
	 * @param lang
	 */
	public setLang(lang: LangType): void {
		this.validatorMessage.changeLang(lang);
	}

	/**
	 * 验证
	 * @param data
	 * @returns
	 */
	public async validate(
		data: Record<string, any>,
		callback?: (result: boolean, errorMessage: any[]) => void,
	): Promise<any> {
		// 防止重复调用
		if (this.state === ValidateState.PENDING) {
			console.error(
				'In form validation, it is forbidden to call repeatedly.',
			);
			return false;
		}
		const rules = this.rules as Record<
			string,
			IValidateRule | IValidateRule[]
		>;
		const { promise, resolve, reject } = defer();
		this.state = ValidateState.PENDING; // 设置状态
		for (const key in rules) {
			// @ts-ignore
			const fieldRules: IValidateRule[] = isType(rules[key], 'object')
				? [rules[key]]
				: rules[key];
			const itemValidateResult = await this._validate(
				key,
				data[key],
				fieldRules,
			);
			this.setResultCache(itemValidateResult.name, itemValidateResult); // 设置验证结果缓存
			console.log(itemValidateResult);
			// 验证失败，获取对应的错误message
			if (itemValidateResult.result === false) {
				// 根据验证结果获取错误信息
				const errorMessage = this.getErrorMessage(
					itemValidateResult.rule as IValidateRule,
					itemValidateResult,
				);
				this.setResultMessage(key, errorMessage);
				this.runError(key, errorMessage, data[key]);
			} else {
				this.runSuccess(key);
			}
		}

		this.state = ValidateState.IDLE; // 改变状态

		// 是否使用callback
		if (typeof callback === 'function') {
			callback(this.resultState, this.errorMessage);
		}

		if (this.resultState) {
			resolve();
		} else {
			reject(this.errorMessage);
		}
		return promise;
	}

	/**
	 * 验证部分字段
	 * @param data
	 * @param fields
	 */
	async validateField(data: any, fields: string[]) {}

	/**
	 * 成功事件
	 * @param callback
	 */
	public onSuccess(callback: (fieldName: string) => void) {
		this._pubSubCenter.subscribe('validate:success', callback);
	}

	/**
	 * 失败事件
	 * @param callback
	 */
	public onError(
		callback: (fieldName: string, message: string, data: any) => void,
	) {
		this._pubSubCenter.subscribe(
			'validate:error',
			function (data: any[], oldData) {
				// @ts-ignore
				callback(data[0], data[1], data[2]);
			},
		);
	}

	/**
	 * 设置缓存
	 * @param fieldName
	 * @param ruleResult
	 */
	private setResultCache(fieldName: string, ruleResult: any) {
		this.resultCache[fieldName] = ruleResult;
	}

	/**
	 * 设置错误信息
	 * @param fieldName
	 * @param message
	 */
	private setResultMessage(fieldName: string, message: string) {
		this.errorMessage.push({
			field: fieldName,
			message: message,
		});
	}

	/**
	 * 获取errorMessage
	 * @param rule
	 * @returns
	 */
	private getErrorMessage(
		rule: IValidateRule,
		validateResult: IValidateResult,
	): string {
		// 如果是自定义验证的，直接取错误信息
		if (validateResult.type === 'validator') {
			return validateResult.validatorErrorMessage as string;
		}
		// 是否配置默认提示
		let _defaultMessage = validateResult?.rule?.message;
		if (_defaultMessage) {
			return _defaultMessage;
		}
		// 如果是必填的
		if (validateResult.type === 'required') {
			return this.validatorMessage.parse('notNull', rule.params || []);
		}
		// 如果没有定义message，则需要再message码表中去匹配
		if (typeof _defaultMessage === 'undefined') {
			const type = validateResult.rule?.pattern;
			if (type) {
				const _msg = this.validatorMessage.parse(
					String(type),
					rule.params || [],
				);
				return _msg;
			}
		}
		return _defaultMessage as string;
	}

	/**
	 * 验证方法
	 * @param _validateKey 验证的字段key
	 * @param _validateData 验证的数据
	 * @param rules 验证字段的一则
	 */
	private _validate(
		_validateKey: string,
		_validateData: any,
		rules: IValidateRule[],
	): Promise<IValidateResult> {
		return validate(_validateData, rules, _validateKey);
	}

	/**
	 * 运行成功
	 * @param fieldName
	 */
	private runSuccess(fieldName: string) {
		this._pubSubCenter.publish('validate:success', fieldName, fieldName);
	}

	/**
	 * 运行成功
	 * @param fieldName
	 */
	private runError(fieldName: string, message: string, data: any) {
		this._pubSubCenter.publish(
			'validate:error',
			[fieldName, message, data],
			message,
		);
	}
}
